package com.guet; // 声明包名为com.guet

import javax.swing.*; // 导入用于图形用户界面的Swing库
import java.awt.*; // 导入用于图形界面的AWT库
import java.awt.event.*; // 导入用于事件处理的AWT事件库
import java.util.Map; // 导入用于存储键值对的Map接口

// 定义类rootJFrame，继承自JFrame，表示一个窗口
public class rootJFrame extends JFrame {
    static String startName = ""; // 静态变量，用于存储起点名称
    static String endName = ""; // 静态变量，用于存储终点名称
    private fileUse f = new fileUse(); // 创建fileUse类的实例，用于文件操作
    private int logicX = 0, logicY = 0, realX, realY; // 定义坐标变量
    public Map<Integer, vexsinfo> vexs = new fileUse().getAllVex(); // 从文件中获取所有节点信息

    // 显示起点和终点的方法
    public void showStartAndEnd() {
        vexsinfo v = f.getVexByName(startName); // 获取起点信息
        vexsinfo v1 = f.getVexByName(endName); // 获取终点信息
        MyJFrame.drawPanel.showPoints.clear(); // 清空显示点
        if (!startName.equals("")) MyJFrame.drawPanel.showPoints.put(v.id, v); // 如果起点名称不为空，添加起点
        if (!endName.equals("")) MyJFrame.drawPanel.showPoints.put(v1.id, v1); // 如果终点名称不为空，添加终点
        MyJFrame.drawPanel.repaint(); // 重新绘制面板
    }

    // 构造函数，初始化窗口
    public rootJFrame(int x) {
        setSize(600, 800); // 设置窗口大小
        setLocation(x, 0); // 设置窗口位置
        setTitle("管理员端"); // 设置窗口标题

        JPanel panel = new JPanel(); // 创建一个面板
        panel.setLayout(new GridBagLayout()); // 设置面板布局为网格包布局
        panel.setBackground(new Color(245, 245, 245)); // 设置面板背景颜色
        GridBagConstraints gbc = new GridBagConstraints(); // 创建网格包布局约束
        gbc.insets = new Insets(5, 5, 5, 5); // 设置边距
        gbc.fill = GridBagConstraints.HORIZONTAL; // 设置填充方式为水平填充

        JLabel startLabel = new JLabel("起点:"); // 创建标签，显示"起点"
        startLabel.setFont(new Font("黑体", Font.BOLD, 16)); // 设置字体
        JLabel endLabel = new JLabel("终点:"); // 创建标签，显示"终点"
        endLabel.setFont(new Font("黑体", Font.BOLD, 16)); // 设置字体

        JComboBox<String> startCom = new JComboBox<>(); // 创建下拉框，用于选择起点
        JComboBox<String> endCom = new JComboBox<>(); // 创建下拉框，用于选择终点
        JButton startSearchBtn = new JButton("查找"); // 创建按钮，显示"查找"
        JButton endSearchBtn = new JButton("查找"); // 创建按钮，显示"查找"

        JLabel transportWayLabel = new JLabel("交通方式:"); // 创建标签，显示"交通方式"
        transportWayLabel.setFont(new Font("黑体", Font.BOLD, 16)); // 设置字体

        ButtonGroup buttonGroup = new ButtonGroup(); // 创建按钮组
        JRadioButton walk = new JRadioButton("步行"); // 创建单选按钮，显示"步行"
        JRadioButton cycling = new JRadioButton("骑行"); // 创建单选按钮，显示"骑行"
        JRadioButton driving = new JRadioButton("驾车"); // 创建单选按钮，显示"驾车"
        JRadioButton walkAndCycling = new JRadioButton("步行+骑行"); // 创建单选按钮，显示"步行+骑行"
        JRadioButton walkAndDriving = new JRadioButton("步行+驾车"); // 创建单选按钮，显示"步行+驾车"

        JLabel periodLabel = new JLabel("时间段"); // 创建标签，显示"时间段"
        periodLabel.setFont(new Font("黑体", Font.BOLD, 16)); // 设置字体
        JComboBox<String> periodCom = new JComboBox<>(); // 创建下拉框，用于选择时间段

        JButton setDistaceBtn = new JButton("设置两点间的距离(加边)"); // 创建按钮，显示"设置两点间的距离(加边)"
        JButton showBtn = new JButton("显示所有点和边"); // 创建按钮，显示"显示所有点和边"
        JButton addVexBtn = new JButton("新增结点(双击地图选点)"); // 创建按钮，显示"新增结点(双击地图选点)"

        setButtonStyle(startSearchBtn); // 设置按钮样式
        setButtonStyle(endSearchBtn); // 设置按钮样式
        setButtonStyle(setDistaceBtn); // 设置按钮样式
        setButtonStyle(showBtn); // 设置按钮样式
        setButtonStyle(addVexBtn); // 设置按钮样式

        gbc.gridx = 0; // 设置网格位置
        gbc.gridy = 0; // 设置网格位置
        panel.add(startLabel, gbc); // 添加组件到面板

        gbc.gridx = 1; // 设置网格位置
        gbc.gridy = 0; // 设置网格位置
        panel.add(startCom, gbc); // 添加组件到面板

        gbc.gridx = 2; // 设置网格位置
        gbc.gridy = 0; // 设置网格位置
        panel.add(startSearchBtn, gbc); // 添加组件到面板

        gbc.gridx = 0; // 设置网格位置
        gbc.gridy = 1; // 设置网格位置
        panel.add(endLabel, gbc); // 添加组件到面板

        gbc.gridx = 1; // 设置网格位置
        gbc.gridy = 1; // 设置网格位置
        panel.add(endCom, gbc); // 添加组件到面板

        gbc.gridx = 2; // 设置网格位置
        gbc.gridy = 1; // 设置网格位置
        panel.add(endSearchBtn, gbc); // 添加组件到面板

        gbc.gridx = 0; // 设置网格位置
        gbc.gridy = 2; // 设置网格位置
        panel.add(transportWayLabel, gbc); // 添加组件到面板

        gbc.gridx = 1; // 设置网格位置
        gbc.gridy = 2; // 设置网格位置
        panel.add(walk, gbc); // 添加组件到面板

        gbc.gridx = 2; // 设置网格位置
        gbc.gridy = 2; // 设置网格位置
        panel.add(cycling, gbc); // 添加组件到面板

        gbc.gridx = 1; // 设置网格位置
        gbc.gridy = 3; // 设置网格位置
        panel.add(driving, gbc); // 添加组件到面板

        gbc.gridx = 2; // 设置网格位置
        gbc.gridy = 3; // 设置网格位置
        panel.add(walkAndCycling, gbc); // 添加组件到面板

        gbc.gridx = 1; // 设置网格位置
        gbc.gridy = 4; // 设置网格位置
        panel.add(walkAndDriving, gbc); // 添加组件到面板

        gbc.gridx = 0; // 设置网格位置
        gbc.gridy = 5; // 设置网格位置
        panel.add(periodLabel, gbc); // 添加组件到面板

        gbc.gridx = 1; // 设置网格位置
        gbc.gridy = 5; // 设置网格位置
        panel.add(periodCom, gbc); // 添加组件到面板

        gbc.gridx = 0; // 设置网格位置
        gbc.gridy = 6; // 设置网格位置
        gbc.gridwidth = 3; // 设置网格宽度
        panel.add(setDistaceBtn, gbc); // 添加组件到面板

        gbc.gridx = 0; // 设置网格位置
        gbc.gridy = 7; // 设置网格位置
        gbc.gridwidth = 3; // 设置网格宽度
        panel.add(showBtn, gbc); // 添加组件到面板

        gbc.gridx = 0; // 设置网格位置
        gbc.gridy = 8; // 设置网格位置
        gbc.gridwidth = 3; // 设置网格宽度
        panel.add(addVexBtn, gbc); // 添加组件到面板

        buttonGroup.add(walk); // 将单选按钮添加到按钮组
        buttonGroup.add(cycling); // 将单选按钮添加到按钮组
        buttonGroup.add(driving); // 将单选按钮添加到按钮组
        buttonGroup.add(walkAndCycling); // 将单选按钮添加到按钮组
        buttonGroup.add(walkAndDriving); // 将单选按钮添加到按钮组

        startCom.addItem("选择起始位置"); // 添加选项到起点下拉框
        endCom.addItem("选择终点位置"); // 添加选项到终点下拉框

        // 将所有节点名称添加到起点和终点下拉框
        for (vexsinfo v : new fileUse().getAllVex().values()) {
            startCom.addItem(v.name); // 添加节点名称到起点下拉框
            endCom.addItem(v.name); // 添加节点名称到终点下拉框
        }

        // 定义时间段数组，并将每个时间段添加到时间段下拉框
        String[] timeItem = {"当前时间", "00:00 ~ 11:15", "11:15 ~ 12:30", "12:30 ~ 14:00", "14:30 ~ 17:35", "17:35 ~ 18:35", "18:35 ~ 20:00", "20:00 ~ 21:00", "21:00 ~ 24:00"};
        for (String t : timeItem) {
            periodCom.addItem(t); // 添加时间段到时间段下拉框
        }

        // 为起点查找按钮添加鼠标点击事件监听器
        startSearchBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                searchNameJFrame searchnamejframe = new searchNameJFrame(getWidth(), 0); // 创建搜索窗口
                searchnamejframe.addWindowListener(new WindowAdapter() {
                    @Override
                    public void windowClosed(WindowEvent e) {
                        super.windowClosed(e);
                        showStartAndEnd(); // 显示起点和终点
                        startCom.setSelectedItem(startName); // 设置选中的起点
                    }
                });
            }
        });

        // 为终点查找按钮添加鼠标点击事件监听器
        endSearchBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                searchNameJFrame searchnamejframe = new searchNameJFrame(getWidth(), 1); // 创建搜索窗口
                searchnamejframe.addWindowListener(new WindowAdapter() {
                    @Override
                    public void windowClosed(WindowEvent e) {
                        super.windowClosed(e);
                        showStartAndEnd(); // 显示起点和终点
                        endCom.setSelectedItem(endName); // 设置选中的终点
                    }
                });
            }
        });

        // 为起点下拉框添加动作事件监听器
        startCom.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (startCom.getSelectedItem().toString().equals("选择起始位置")) {
                    startName = ""; // 如果选择的是"选择起始位置"，将起点名称设为空
                    showStartAndEnd(); // 显示起点和终点
                    return;
                }
                startName = startCom.getSelectedItem().toString(); // 获取选中的起点名称
                MyJFrame.drawPanel.shortest.clear(); // 清空最短路径
                showStartAndEnd(); // 显示起点和终点
            }
        });

        // 为终点下拉框添加动作事件监听器
        endCom.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (endCom.getSelectedItem().toString().equals("选择终点位置")) {
                    endName = ""; // 如果选择的是"选择终点位置"，将终点名称设为空
                    showStartAndEnd(); // 显示起点和终点
                    return;
                }
                endName = endCom.getSelectedItem().toString(); // 获取选中的终点名称
                MyJFrame.drawPanel.shortest.clear(); // 清空最短路径
                showStartAndEnd(); // 显示起点和终点
            }
        });

        // 为设置两点间距离按钮添加鼠标点击事件监听器
        setDistaceBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                f.setTwoPointDistance(startCom.getSelectedItem().toString(), endCom.getSelectedItem().toString()); // 设置两点间距离
            }
        });

        // 为显示所有点和边按钮添加鼠标点击事件监听器
        showBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                MyJFrame.drawPanel.shortest.clear(); // 清空最短路径
                MyJFrame.drawPanel.alg.mGraph = new MGraph(); // 重新初始化图
                if (MyJFrame.drawPanel.showAll == 1) {
                    MyJFrame.drawPanel.showAll = 0; // 如果当前显示所有点和边，则取消显示
                    showBtn.setText("显示所有结点及边"); // 设置按钮文本
                } else {
                    MyJFrame.drawPanel.showAll = 1; // 否则，显示所有点和边
                    showBtn.setText("取消显示所有结点及边"); // 设置按钮文本
                }
                MyJFrame.drawPanel.repaint(); // 重新绘制面板
            }
        });

        // 为画板添加鼠标点击事件监听器
        MyJFrame.drawPanel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                if (e.getClickCount() == 1) {
                    vexsinfo v = new vexsinfo();
                    v.logicx = e.getX(); // 获取逻辑X坐标
                    v.logicy = e.getY(); // 获取逻辑Y坐标
                    logicX = v.logicx; // 保存逻辑X坐标
                    logicY = v.logicy; // 保存逻辑Y坐标
                    v.name = "新结点逻辑坐标"; // 设置结点名称
                    MyJFrame.drawPanel.showPoints.put(0, v); // 显示点
                    MyJFrame.drawPanel.repaint(); // 重新绘制面板
                } else {
                    vexsinfo v = new vexsinfo();
                    v.logicx = e.getX(); // 获取真实X坐标
                    v.logicy = e.getY(); // 获取真实Y坐标
                    realX = v.logicx; // 保存真实X坐标
                    realY = v.logicy; // 保存真实Y坐标
                    v.name = "新结点真实坐标"; // 设置结点名称
                    MyJFrame.drawPanel.showPoints.put(1, v); // 显示点
                    MyJFrame.drawPanel.repaint(); // 重新绘制面板
                }
            }
        });

        // 为新增结点按钮添加鼠标点击事件监听器
        addVexBtn.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                super.mouseClicked(e);
                if (logicX == 0 || logicY == 0) {
                    JOptionPane.showMessageDialog(null, "先在地图双击选逻辑位置和单击选实际位置"); // 显示提示信息
                    return;
                }
                showAddNodeDialog(); // 显示新增结点对话框
            }
        });

        add(panel); // 将面板添加到窗口
        setVisible(true); // 设置窗口可见
    }

    // 设置按钮样式的方法
    private void setButtonStyle(JButton button) {
        button.setBackground(new Color(34, 139, 34)); // 设置按钮背景颜色
        button.setForeground(Color.WHITE); // 设置按钮前景颜色
        button.setFont(new Font("黑体", Font.BOLD, 16)); // 设置按钮字体
        button.setFocusPainted(false); // 设置按钮无焦点绘制
        button.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createLineBorder(new Color(34, 139, 34), 2), // 设置按钮边框颜色
                BorderFactory.createEmptyBorder(5, 15, 5, 15) // 设置按钮内边距
        ));
    }

    // 显示新增结点对话框的方法
    private void showAddNodeDialog() {
        JTextField nameField = new JTextField(); // 创建文本框，用于输入结点名称
        JCheckBox driveCheckBox = new JCheckBox("可通车"); // 创建复选框，用于选择是否可通车
        JTextField topNodeField = new JTextField(); // 创建文本框，用于输入上结点
        JTextField bottomNodeField = new JTextField(); // 创建文本框，用于输入下结点
        JTextField leftNodeField = new JTextField(); // 创建文本框，用于输入左结点
        JTextField rightNodeField = new JTextField(); // 创建文本框，用于输入右结点
        JTextField introField = new JTextField(); // 创建文本框，用于输入简介
        JTextField busyTimeField = new JTextField(); // 创建文本框，用于输入繁忙时间点

        Object[] message = {
                "节点名称:", nameField,
                "是否可通车:", driveCheckBox,
                "上结点 (没有则输入-1):", topNodeField,
                "下结点 (没有则输入-1):", bottomNodeField,
                "左结点 (没有则输入-1):", leftNodeField,
                "右结点 (没有则输入-1):", rightNodeField,
                "简介:", introField,
                "繁忙时间点 (如 11:35, 没有则留空):", busyTimeField
        };

        int option = JOptionPane.showConfirmDialog(null, message, "新增结点", JOptionPane.OK_CANCEL_OPTION); // 显示对话框
        if (option == JOptionPane.OK_OPTION) {
            vexsinfo v = new vexsinfo();
            v.name = nameField.getText(); // 获取结点名称
            v.drive = driveCheckBox.isSelected() ? 1 : 0; // 获取是否可通车
            String[] dir = new String[4];
            dir[0] = topNodeField.getText(); // 获取上结点
            dir[1] = bottomNodeField.getText(); // 获取下结点
            dir[2] = leftNodeField.getText(); // 获取左结点
            dir[3] = rightNodeField.getText(); // 获取右结点

            for (int i = 0; i < 4; i++) {  // 修改新结点的对应结点对应自己
                if (dir[i].equals("-1")) {
                    switch (i) {
                        case 0:
                            v.top = -1; // 设置上结点为-1
                            break;
                        case 1:
                            v.bottom = -1; // 设置下结点为-1
                            break;
                        case 2:
                            v.left = -1; // 设置左结点为-1
                            break;
                        case 3:
                            v.right = -1; // 设置右结点为-1
                            break;
                    }
                    continue;
                }
                for (vexsinfo vex : f.getAllVex().values()) {
                    if (vex.name.equals(dir[i])) {
                        switch (i) {
                            case 0:
                                v.top = vex.id; // 设置上结点ID
                                break;
                            case 1:
                                v.bottom = vex.id; // 设置下结点ID
                                break;
                            case 2:
                                v.left = vex.id; // 设置左结点ID
                                break;
                            case 3:
                                v.right = vex.id; // 设置右结点ID
                                break;
                        }
                    }
                }
            }

            v.position = v.name.contains("路口") ? 0 : 1; // 判断是否是路口
            v.logicx = logicX; // 设置逻辑X坐标
            v.logicy = logicY; // 设置逻辑Y坐标
            if (v.position == 0) {
                MyJFrame.drawPanel.showPoints.remove(1); // 移除显示点
                MyJFrame.drawPanel.repaint(); // 重新绘制面板
                v.realx = logicX; // 设置真实X坐标
                v.realy = logicY; // 设置真实Y坐标
            } else {
                v.realx = realX; // 设置真实X坐标
                v.realy = realY; // 设置真实Y坐标
            }
            int max = 0;
            for (vexsinfo vex : f.getAllVex().values()) {
                if (vex.id > max) {
                    max = vex.id; // 获取最大ID
                }
            }
            v.id = max + 1; // 设置新结点ID
            String busyTime = busyTimeField.getText(); // 获取繁忙时间点
            if (!busyTime.equals("")) {
                // 写入存在时间段繁忙的队伍文件中
                new fileUse().addCrowded(v.name); // 添加繁忙时间
            } else {
                v.croded_level = 1.0F; // 设置繁忙等级
            }
            v.introduction = introField.getText(); // 设置简介

            // 文件更新邻结点，文件增加结点
            f.updateVexDir(v.id, dir); // 更新邻结点
            f.addVex(v); // 添加结点
        }
    }
}
